home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / drivers.arc / NI5010.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-10-20  |  17.3 KB  |  709 lines

  1. version    equ    3
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ;Ported from Bill Doster's il.c, a C-language driver for the Interlan NI5010
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7.  
  8. ;/* PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  9. ;*  Portions (C) Copyright 1988 Bill Doster
  10. ;*
  11. ;*  Permission is granted to any individual or institution to use, copy,
  12. ;*  modify, or redistribute this software and its documentation provided
  13. ;*  this notice and the copyright notices are retained.  This software may
  14. ;*  not be distributed for profit, either in original form or in derivative
  15. ;*  works.  Bill Doster makes no representations about the suitability
  16. ;*  of this software for any purpose.  BILL DOSTER GIVES NO WARRANTY,
  17. ;*  EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
  18. ;*  PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
  19. ;*  AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  20. ;*/
  21.  
  22. code    segment    byte public
  23.     assume    cs:code, ds:code
  24.  
  25. ; The various IE command registers
  26. EDLC_XSTAT    equ    0        ; EDLC transmit csr
  27. EDLC_XCLR    equ    0        ; EDLC transmit "Clear IRQ"
  28. EDLC_XMASK    equ    1        ; EDLC transmit "IRQ Masks"
  29. EDLC_RSTAT    equ    2        ; EDLC receive csr
  30. EDLC_RCLR    equ    2        ; EDLC receive "Clear IRQ"
  31. EDLC_RMASK    equ    3        ; EDLC receive "IRQ Masks"
  32. EDLC_XMODE    equ    4        ; EDLC transmit Mode
  33. EDLC_RMODE    equ    5        ; EDLC receive Mode
  34. EDLC_RESET    equ    6        ; EDLC RESET register
  35. EDLC_TDR1    equ    7        ; "Time Domain Reflectometry" reg1
  36. EDLC_ADDR    equ    8        ; EDLC station address, 6 bytes
  37.                     ; 0Eh doesn't exist for r/w
  38. EDLC_TDR2    equ    0fh        ; "Time Domain Reflectometry" reg2
  39. IE_GP        equ    10h        ; GP pointer (word register)
  40.                     ; 11h is 2nd byte of GP Pointer
  41. IE_RCNT        equ    10h        ; Count of bytes in rcv'd packet
  42.                     ; 11h is 2nd byte of "Byte Count"
  43. IE_MMODE    equ    12h        ; Memory Mode register
  44. IE_DMA_RST    equ    13h        ; IE DMA Reset.  write only
  45. IE_ISTAT    equ    13h        ; IE Interrupt Status.  read only
  46. IE_RBUF        equ    14h        ; IE Receive Buffer port
  47. IE_XBUF        equ    15h        ; IE Transmit Buffer port
  48. IE_SAPROM    equ    16h        ; window on station addr prom
  49. IE_RESET    equ    17h        ; any write causes Board Reset
  50.  
  51. ; bits in EDLC_XSTAT, interrupt clear on write, status when read
  52. XS_TPOK        equ    80h        ; transmit packet successful
  53. XS_CS        equ    40h        ; carrier sense
  54. XS_RCVD        equ    20h        ; transmitted packet received
  55. XS_SHORT    equ    10h        ; transmission media is shorted
  56. XS_UFLW        equ    08h        ; underflow.  iff failed board
  57. XS_COLL        equ    04h        ; collision occurred
  58. XS_16COLL    equ    02h        ; 16th collision occurred
  59. XS_PERR        equ    01h        ; parity error
  60.  
  61. XS_CLR_UFLW    equ    08h        ; clear underflow
  62. XS_CLR_COLL    equ    04h        ; clear collision
  63. XS_CLR_16COLL    equ    02h        ; clear 16th collision
  64. XS_CLR_PERR    equ    01h        ; clear parity error
  65.  
  66. ; bits in EDLC_XMASK, mask/enable transmit interrupts.  register is r/w
  67. XM_TPOK        equ    80h        ; =1 to enable Xmt Pkt OK interrupts
  68. XM_RCVD        equ    20h        ; =1 to enable Xmt Pkt Rcvd ints
  69. XM_UFLW        equ    08h        ; =1 to enable Xmt Underflow ints
  70. XM_COLL        equ    04h        ; =1 to enable Xmt Collision ints
  71. XM_COLL16    equ    02h        ; =1 to enable Xmt 16th Coll ints
  72. XM_PERR        equ    01h        ; =1 to enable Xmt Parity Error ints
  73.                     ; note: always clear this bit
  74.  
  75. ; bits in EDLC_RSTAT, interrupt clear on write, status when read
  76. RS_PKT_OK    equ    80h        ; received good packet
  77. RS_RST_PKT    equ    10h        ; RESET packet received
  78. RS_RUNT        equ    08h        ; Runt Pkt rcvd.  Len < 64 Bytes
  79. RS_ALIGN    equ    04h        ; Alignment error. not 8 bit aligned
  80. RS_CRC_ERR    equ    02h        ; Bad CRC on rcvd pkt
  81. RS_OFLW        equ    01h        ; overflow for rcv FIFO
  82. RS_VALID_BITS    equ    RS_PKT_OK or RS_RST_PKT or RS_RUNT or RS_ALIGN or RS_CRC_ERR or RS_OFLW
  83.                     ; all valid RSTAT bits
  84.  
  85. RS_CLR_PKT_OK    equ    80h        ; clear rcvd packet interrupt
  86. RS_CLR_RST_PKT    equ    10h        ; clear RESET packet received
  87. RS_CLR_RUNT    equ    08h        ; clear Runt Pckt received
  88. RS_CLR_ALIGN    equ    04h        ; clear Alignment error
  89. RS_CLR_CRC_ERR    equ    02h        ; clear CRC error
  90. RS_CLR_OFLW    equ    01h        ; clear rcv FIFO Overflow
  91.  
  92. ; bits in EDLC_RMASK, mask/enable receive interrupts.  register is r/w
  93. RM_PKT_OK    equ    80h        ; =1 to enable rcvd good packet ints
  94. RM_RST_PKT    equ    10h        ; =1 to enable RESET packet ints
  95. RM_RUNT        equ    08h        ; =1 to enable Runt Pkt rcvd ints
  96. RM_ALIGN    equ    04h        ; =1 to enable Alignment error ints
  97. RM_CRC_ERR    equ    02h        ; =1 to enable Bad CRC error ints
  98. RM_OFLW        equ    01h        ; =1 to enable overflow error ints
  99.  
  100. ; bits in EDLC_RMODE, set Receive Packet mode.  register is r/w
  101. RMD_TEST    equ    80h        ; =1 for Chip testing.  normally 0
  102. RMD_ADD_SIZ    equ    10h        ; =1 5-byte addr match.  normally 0
  103. RMD_EN_RUNT    equ    08h        ; =1 enable runt rcv.  normally 0
  104. RMD_EN_RST    equ    04h        ; =1 to rcv RESET pkt.  normally 0
  105.  
  106. RMD_PROMISC    equ    03h        ; receive *all* packets.  unusual
  107. RMD_MULTICAST    equ    02h        ; receive multicasts too.  unusual
  108. RMD_BROADCAST    equ    01h        ; receive broadcasts & normal. usual
  109. RMD_NO_PACKETS    equ    00h        ; don't receive any packets. unusual
  110.  
  111. ; bits in EDLC_XMODE, set Transmit Packet mode.  register is r/w
  112. XMD_COLL_CNT    equ    0f0h        ; coll's since success.  read-only
  113. XMD_IG_PAR    equ    008h        ; =1 to ignore parity.  ALWAYS set
  114. XMD_T_MODE    equ    004h        ; =1 to power xcvr. ALWAYS set this
  115. XMD_LBC        equ    002h        ; =1 for loopbakc.  normally set
  116. XMD_DIS_C    equ    001h        ; =1 disables contention. normally 0
  117.  
  118. ; bits in EDLC_RESET, write only
  119. RS_RESET    equ    80h        ; =1 to hold EDLC in reset state
  120.  
  121. ; bits in IE_MMODE, write only
  122. MM_EN_DMA    equ    80h        ; =1 begin DMA xfer, Cplt clrs it
  123. MM_EN_RCV    equ    40h        ; =1 allows Pkt rcv.  clr'd by rcv
  124. MM_EN_XMT    equ    20h        ; =1 begin Xmt pkt.  Cplt clrs it
  125. MM_BUS_PAGE    equ    18h        ; =00 ALWAYS.  Used when MUX=1
  126. MM_NET_PAGE    equ    06h        ; =00 ALWAYS.  Used when MUX=0
  127. MM_MUX        equ    01h        ; =1 means Rcv Buff on system bus
  128.                     ; =0 means Xmt Buff on system bus
  129.  
  130. ; bits in IE_ISTAT, read only
  131. IS_TDIAG    equ    80h        ; =1 if Diagnostic problem
  132. IS_EN_RCV    equ    20h        ; =1 until frame is rcv'd cplt
  133. IS_EN_XMT    equ    10h        ; =1 until frame is xmt'd cplt
  134. IS_EN_DMA    equ    08h        ; =1 until DMA is cplt or aborted
  135. IS_DMA_INT    equ    04h        ; =0 iff DMA done interrupt. 
  136. IS_R_INT    equ    02h        ; =0 iff unmasked Rcv interrupt
  137. IS_X_INT    equ    01h        ; =0 iff unmasked Xmt interrupt
  138.  
  139. BFRSIZ        equ    2048    ;number of bytes in a buffer
  140.  
  141.     public    int_no
  142. int_no        db    3,0,0,0        ; interrupt number.
  143. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  144. ipkt_size    dw    ?
  145. opkt_size    dw    ?
  146.  
  147.     public    driver_class, driver_type, driver_name
  148. driver_class    db    1        ;from the packet spec
  149. driver_type    db    3        ;from the packet spec
  150. driver_name    db    'NI5010',0    ;name of the driver.
  151.  
  152. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  153. our_type    dw    ?
  154. intstat        db    ?
  155.  
  156.     public    send_pkt
  157. send_pkt:
  158. ;enter with ds:si -> packet, cx = packet length.
  159. ;exit with nc if ok, or else cy if error, dh set to error number.
  160.     assume    ds:nothing
  161.     cmp    cx,RUNT        ; minimum length for Ether
  162.     jae    oklen
  163.     mov    cx,RUNT        ; make sure size at least RUNT
  164. oklen:
  165.     inc    cx            ;round size up to next even number.
  166.     and    cx,not 1
  167.  
  168. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  169. ;only in the transmit mode, hence the initial check.
  170.  
  171.     loadport
  172.     setport    IE_ISTAT
  173.     in    al,dx
  174.     and    al,IS_EN_XMT        ;on-going xmit
  175.     je    send_pkt_2
  176.  
  177.     mov    bx,20000        ;try this many times.
  178. send_pkt_3:
  179.     in    al,dx            ;if not busy, exit.
  180.     and    al,IS_EN_XMT
  181.     je    send_pkt_2
  182.     dec    bx
  183.     jne    send_pkt_3
  184.     mov    dh,CANT_SEND        ;timed out, can't send.
  185.     stc
  186.     ret
  187. send_pkt_2:
  188.  
  189.     pushf            ; No distractions from the receiver
  190.     cli
  191.  
  192. ; Disable the Receiver
  193.     mov    al, 0        ; Mask all Receive Interrupts
  194.     loadport
  195.     setport    EDLC_RMASK
  196.     out    dx,al
  197.  
  198.     mov    al, 0        ; Put Xmt Buffer on System Bus
  199.     setport    IE_MMODE
  200.     out    dx,al
  201.  
  202.     mov    al, 0FFh    ; Clear out any pending Rcv Ints
  203.     setport    EDLC_RCLR
  204.     out    dx,al
  205.  
  206.     mov    ax, BFRSIZ    ; Point GP at beginning of packet
  207.     sub    ax,cx
  208.     setport    IE_GP
  209.     out    dx,ax
  210.  
  211.     setport    IE_XBUF
  212.  
  213.     mov    opkt_size,cx    ; opkt_size = cx;
  214.     cmp    is_186,0    ; Can we use rep outsb?
  215.     je    out86        ; no - have to do it slowly.
  216.     rep    outsb
  217.     jmp    short ocnteven
  218. out86:
  219.     test    si,1        ; (buf & 1) ?
  220.     jz    obufeven    ; no
  221.     lodsb            ; al = *si++;
  222.     out    dx,al        ; out(dx,al);
  223.     dec    cx        ; cx--;
  224. obufeven:
  225.     mov    di,cx        ; save for later test
  226.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  227. ; Do the bulk of the buffer, a word at a time
  228.     jcxz    onobuf        ; if(cx != 0){
  229. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  230.     out    dx,al        ; out(dx,lowbyte(ax));
  231.     mov    al,ah
  232.     out    dx,al        ; out(dx,hibyte(ax));
  233.     loop    xb        ; } while(--cx != 0); }
  234. ; now check for odd trailing byte
  235. onobuf:    shr    di,1        ; if (di & 1)
  236.     jnc    ocnteven
  237.     lodsb            ;   out(dx,*si++);
  238.     out    dx,al
  239. ocnteven:
  240.  
  241. ; Rewrite where packet starts
  242.     mov    ax,BFRSIZ
  243.     sub    ax,opkt_size
  244.     loadport
  245.     setport    IE_GP
  246.     out    dx,ax
  247.  
  248. ; Flip Xmt Buffer to EDLC Bus so it can be transmitted
  249.     mov    al, MM_MUX
  250.     setport    IE_MMODE
  251.     out    dx,al
  252.  
  253. ; Begin transmission.
  254.     mov    al, MM_EN_XMT or MM_MUX
  255.     setport    IE_MMODE
  256.     out    dx,al
  257.  
  258. ; Cause interrupt after completion (or if something fails)
  259.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  260.     setport    EDLC_XMASK
  261.     out    dx,al
  262.  
  263.     popf
  264.  
  265.     ret
  266.  
  267.  
  268.     public    get_address
  269. get_address:
  270. ;get the address of the interface.
  271. ;enter with es:di -> place to get the address, cx = size of address buffer.
  272. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  273.     assume    ds:code
  274.     cmp    cx,EADDR_LEN            ;make sure that we have enough room.
  275.     jb    get_address_2
  276.     cmp    cx,9            ;do we have room for all of it?
  277.     jb    get_address_3        ;no.
  278.     mov    cx,9            ;yes - get the whole thing.
  279.     xor    bx,bx
  280.     jmp    short get_address_1
  281. get_address_3:
  282.     mov    cx,EADDR_LEN
  283.     xor    bx,bx
  284. get_address_1:
  285.     mov    ax,bx
  286.     loadport
  287.     setport    IE_GP
  288.     out    dx,ax
  289.  
  290.     setport    IE_SAPROM
  291.     in    al,dx
  292.     stosb
  293.     inc    bx
  294.     loop    get_address_1
  295.  
  296.     mov    cx,EADDR_LEN
  297.     clc
  298.     ret
  299. get_address_2:
  300.     stc
  301.     ret
  302.  
  303.  
  304. ;Set Ethernet address on controller
  305. set_address:
  306. ;enter:
  307. ;    ds:si -> address
  308.  
  309.     loadport
  310.     setport    EDLC_ADDR
  311.     mov    cx,EADDR_LEN
  312. set_address_1:
  313.     lodsb
  314.     out    dx,al
  315.     inc    dx
  316.     loop    set_address_1
  317.  
  318.     ret
  319.  
  320. terminate:
  321.     ; put card in held-RESET state
  322.     mov    al,0
  323.     loadport
  324.     setport    IE_MMODE
  325.     out    dx,al
  326.     mov    al,RS_RESET
  327.     loadport
  328.     setport    EDLC_RESET
  329.     out    dx,al
  330.  
  331.     ret
  332.  
  333.  
  334.     public    reset_interface
  335. reset_interface:
  336. ;reset the interface.
  337. ;we don't do anything.
  338.     ret
  339.  
  340.  
  341. ;called when we want to determine what to do with a received packet.
  342. ;enter with cx = packet length, es:di -> packet type.
  343.     extrn    recv_find: near
  344.  
  345. ;called after we have copied the packet into the buffer.
  346. ;enter with ds:si ->the packet, cx = length of the packet.
  347.     extrn    recv_copy: near
  348.  
  349.     extrn    count_in_err: near
  350.     extrn    count_out_err: near
  351.  
  352.     public    recv
  353. recv:
  354. ;called from the recv isr.  All registers have been saved, and ds=cs.
  355. ;Upon exit, the interrupt will be acknowledged.
  356.     assume    ds:code
  357.  
  358.     loadport
  359.     setport    IE_ISTAT
  360.     in    al,dx
  361.     mov    intstat,al
  362.  
  363. ; DMA Complete Interrupt.  We don't use DMA, but just in case ...
  364.     test    al,IS_DMA_INT
  365.     jne    recv_isr_3
  366.  
  367.     mov    al, 0         ; Reset DMA Interrupt
  368.     setport    IE_DMA_RST
  369.     out    dx,al
  370.  
  371. recv_isr_3:
  372.  
  373. ; Transmit Complete/Fail Interrupt
  374.     test    intstat,IS_X_INT
  375.     jne    recv_isr_1
  376.  
  377.     loadport
  378.     setport    EDLC_XSTAT
  379.     in    al,dx
  380.     mov    ah,al
  381.  
  382.     mov    al, 0            ; Disable Xmt IRQ's
  383.     setport    EDLC_XMASK
  384.     out    dx,al
  385.  
  386.     mov    al, 0FFh        ; clr all Xmt IRQ's
  387.     setport    EDLC_XCLR
  388.     out    dx,al
  389.  
  390.     test    ah,XS_COLL
  391.     je    recv_isr_1
  392.     ;Crank counter back to beginning and restart xmt
  393.  
  394.     mov    ax,BFRSIZ        ; Point GP at beginning of packet
  395.     sub    ax,opkt_size
  396.     setport    IE_GP
  397.     out    dx,ax
  398.  
  399.     mov    al, 0        ; De-assert MM_EN_RCV bit Just In Case
  400.     setport    IE_MMODE
  401.     out    dx,al
  402.  
  403.                 ; Flip Xmt Buffer to EDLC Bus and restart xmt
  404.     mov    al, MM_EN_XMT or MM_MUX
  405.     setport    IE_MMODE
  406.     out    dx,al
  407.  
  408.             ; Interrupt for all Transmit errors along with TPOK
  409.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  410.     setport    EDLC_XMASK
  411.     out    dx,al
  412.  
  413.     ret            ; Wait for it to complete again
  414.  
  415. recv_isr_1:
  416.     ; Is this a Receive Packet Interrupt?
  417.     test    intstat,IS_R_INT
  418.     jne    recv_isr_9_j_1        ;no.
  419.  
  420.     loadport
  421.     setport    EDLC_RSTAT        ;get the status of this packet
  422.     in    al,dx
  423.     and    al,RS_VALID_BITS
  424.     cmp    al,RS_PKT_OK        ;is it ok?
  425.     jne    recv_isr_7        ;yes.
  426.  
  427.     ; Clear the interrupt
  428.     mov    al, 0FFh
  429.     loadport
  430.     setport    EDLC_RCLR
  431.     out    dx,al
  432.  
  433.     ; Flip Rcv Buffer onto the system bus
  434.     mov    al, MM_MUX
  435.     setport    IE_MMODE
  436.     out    dx,al
  437.  
  438.     ; Get the size of the packet.
  439.     setport    IE_RCNT
  440.     in    ax,dx
  441.     mov    ipkt_size,ax
  442.  
  443.     cmp    ax,GIANT        ;greater than GIANT?
  444.     jbe    recv_isr_8        ;no.
  445. recv_isr_7:
  446.     call    count_in_err
  447. recv_isr_9_j_1:
  448.     jmp    recv_isr_9
  449. recv_isr_8:
  450. ;Put it on the receive queue
  451.  
  452.     mov    ax,EADDR_LEN+EADDR_LEN            ;seek to the type word.
  453.     setport    IE_GP
  454.     out    dx,ax
  455.  
  456.     setport    IE_RBUF
  457.     in    al,dx            ;read the type word out of the board.
  458.     mov    ah,al
  459.     in    al,dx
  460.     xchg    al,ah            ;should be in network byte order.
  461.     mov    our_type,ax
  462.  
  463.     mov    ax,ds            ;look up our type.
  464.     mov    es,ax
  465.     mov    di,offset our_type
  466.     mov    cx,ipkt_size
  467.     call    recv_find
  468.  
  469.     mov    ax,es            ;is this pointer null?
  470.     or    ax,di
  471.     je    recv_isr_9        ;yes - just free the frame.
  472.  
  473.     push    es            ;remember where the buffer pointer is.
  474.     push    di
  475.  
  476.     xor    ax,ax            ;seek to the beginning again.
  477.     loadport
  478.     setport    IE_GP
  479.     out    dx,ax
  480.  
  481.     mov    cx,ipkt_size
  482.     setport    IE_RBUF
  483.  
  484.     cmp    is_186,0    ; Can we use rep insb?
  485.     je    in86        ; no - have to do it slowly.
  486.     rep    insb
  487.     jmp    short icnteven
  488. in86:
  489. ; If buffer doesn't begin on a word boundary, get the first byte
  490.     test    di,1    ; if(buf & 1){
  491.     jz    ibufeven ;
  492.     in    al,dx    ; al = in(dx);
  493.     stosb        ; *di++ = al
  494.     dec    cx    ; cx--;
  495. ibufeven:
  496.     mov    si,cx    ; size = cx;
  497.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  498. ; Do the bulk of the buffer, a word at a time
  499.     jcxz    inobuf    ; if(cx != 0){
  500. rb:    in    al,dx    ; do { al = in(dx);
  501.     mov    ah,al
  502.     in    al,dx    ; ah = in(dx);
  503.     xchg    al,ah
  504.     stosw        ; *si++ = ax; (di is word pointer)
  505.     loop    rb    ; } while(--cx != 0);
  506. ; now check for odd trailing byte
  507. inobuf:    shr    si,1
  508.     jnc    icnteven
  509.     in    al,dx
  510.     stosb        ; *di++ = al
  511. icnteven:
  512.  
  513.     pop    si
  514.     pop    ds
  515.     assume    ds:nothing
  516.     mov    cx,ipkt_size
  517.     call    recv_copy        ;tell them that we copied it.
  518.  
  519.     mov    ax,cs            ;restore our ds.
  520.     mov    ds,ax
  521.     assume    ds:code
  522.  
  523. recv_isr_9:
  524.  
  525. ; Prime Interlan card for another Receive
  526. il_rcv_reset:
  527.  
  528.     ; Rcv packet at start of Boards buffer
  529.     mov    ax,0
  530.     loadport
  531.     setport    IE_GP
  532.     out    dx,ax
  533.  
  534.     ; Clear any remaining Interrupt conditions
  535.     mov    al,0FFh
  536.     setport    EDLC_RCLR
  537.     out    dx,al
  538.  
  539.     ; Set MUX to allow EDLC to access Rcv Buffer
  540.     mov    al,0
  541.     setport    IE_MMODE
  542.     out    dx,al
  543.  
  544.     ; Enable Receive of Normal and Broadcast Packets only.
  545.     mov    al,RMD_BROADCAST
  546.     setport    EDLC_RMODE
  547.     out    dx,al
  548.  
  549.     ; Enable Receive Interrupts
  550.     mov    al,MM_EN_RCV
  551.     setport    IE_MMODE
  552.     out    dx,al
  553.  
  554.     ; Unmask *all* Receive related interrupts
  555.     mov    al,0FFh
  556.     setport    EDLC_RMASK
  557.     out    dx,al
  558.  
  559.     ret
  560.  
  561.  
  562. end_resident    label    byte
  563.  
  564.     public    usage_msg
  565. usage_msg    db    "usage: NI5010 <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  566.  
  567.     public    copyright_msg
  568. copyright_msg    db    "Packet driver for the Interlan NI5010, version ",'0'+version,CR,LF
  569.         db    "Portions Copyright 1988 Bill Doster",CR,LF,'$'
  570.  
  571.  
  572. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  573. no_ni5010_msg    db    "No NI5010 found at that address.",CR,LF,'$'
  574. ether_bdcst    db    EADDR_LEN dup(-1)    ;ethernet broadcast address.
  575. our_address    db    EADDR_LEN+3 dup(?)    ;temporarily hold our address
  576.  
  577. int_no_name    db    "Interrupt number ",'$'
  578. io_addr_name    db    "I/O port ",'$'
  579.  
  580.     extrn    set_recv_isr: near
  581.  
  582. ;enter with si -> argument string, di -> word to store.
  583. ;if there is no number, don't change the number.
  584.     extrn    get_number: near
  585.  
  586.     public    parse_args
  587. parse_args:
  588.     mov    di,offset int_no
  589.     mov    bx,offset int_no_name
  590.     call    get_number
  591.     mov    di,offset io_addr
  592.     mov    bx,offset io_addr_name
  593.     call    get_number
  594.     ret
  595.  
  596.  
  597. no_ni5010_error:
  598.     mov    dx,offset no_ni5010_msg
  599.     mov    ah,9
  600.     int    21h
  601.     stc
  602.     ret
  603.  
  604.  
  605.     public    etopen
  606. etopen:
  607. ;  Initialize the Ethernet board, set receive type.
  608. ;
  609. ;  check for correct EPROM location
  610. ;
  611.     pushf        ; No distractions from the receiver
  612.     cli
  613.  
  614.     ; Hold up EDLC RESET while the board is configured
  615.     mov    al,RS_RESET
  616.     loadport
  617.     setport    EDLC_RESET
  618.     out    dx,al
  619.  
  620.     ; Hardware reset of Interlan Board
  621.     mov    al,0
  622.     loadport
  623.     setport    IE_RESET
  624.     out    dx,al
  625.  
  626.     call    set_recv_isr
  627.  
  628.     popf        ; Shouldn't be any interrupts from here on out
  629.  
  630.     mov    al,XMD_LBC
  631.     loadport
  632.     setport    EDLC_XMODE
  633.     out    dx,al
  634.  
  635. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  636. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  637.     mov    cl,33
  638.     mov    ax,0ffffh
  639.     shl    ax,cl
  640.     jz    not_186
  641.     mov    is_186,1
  642.     mov    dx,offset using_186_msg
  643.     mov    ah,9
  644.     int    21h
  645. not_186:
  646.  
  647.     push    ds
  648.     pop    es
  649.     mov    di,offset our_address
  650.     mov    cx,9
  651.     call    get_address
  652.     mov    si,offset our_address
  653.     call    set_address
  654.  
  655. ;See if there really is a ni5010 there.
  656.     cmp    our_address+EADDR_LEN+0,0
  657.     jne    no_ni5010
  658.     cmp    our_address+EADDR_LEN+1,055h
  659.     jne    no_ni5010
  660.     cmp    our_address+EADDR_LEN+2,0aah
  661.     jne    no_ni5010
  662.  
  663.     mov    cx,EADDR_LEN
  664.     mov    di,offset ether_bdcst
  665.     repe    cmpsb
  666.     jne    have_ni5010        ;not broadcast address -- must be real.
  667. no_ni5010:
  668.     jmp    no_ni5010_error        ;not there -- no ni5010.
  669. have_ni5010:
  670.  
  671.     ; Only enable Transmit-type interrupts while Transmitting
  672.     mov    al,0
  673.     loadport
  674.     setport    EDLC_XMASK
  675.     out    dx,al
  676.  
  677.     ; Establish generic Transmit mode
  678.     mov    al,XMD_IG_PAR or XMD_T_MODE or XMD_LBC
  679.     setport    EDLC_XMODE
  680.     out    dx,al
  681.  
  682.     ; Clear any startup related Transmit interrupts
  683.     mov    al,0FFh
  684.     setport    EDLC_XCLR
  685.     out    dx,al
  686.  
  687.     ; Establish generic Receive mode
  688.     mov    al,RMD_BROADCAST
  689.     setport    EDLC_RMODE
  690.     out    dx,al
  691.  
  692.     ; Reset Rcv State to allow receives
  693.     call    il_rcv_reset
  694.  
  695.     ; Finally un-reset the EDLC
  696.     mov    al,0
  697.     loadport
  698.     setport    EDLC_RESET
  699.     out    dx,al
  700.  
  701.     mov    dx,offset end_resident
  702.     clc
  703.     ret
  704.  
  705.  
  706. code    ends
  707.  
  708.     end
  709.